#include "log.hpp"
#include "Reactor.hpp"
#include "listener.hpp"
#include "HandleConnection.hpp"
#include "service.hpp"

#include <iostream>
#include <memory>
#include <cstdio>

using namespace log_namespace;

using service_t = std::function<void(int, const std::string &message, inetAddr &who)>;

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        std::cerr << "Usage: " << argv[0] << " local-port" << std::endl;
        exit(0);
    }
    else if (argc == 3)
    {
        FILE *fp;
        if (argv[2] == std::string("i"))
        {
            fp = fopen("./dict.txt", "a+");
            while (true)
            {
                std::string english;
                std::string chinese;
                std::string entry;

                std::cout << "Enter english firstly # ";
                getline(std::cin, english);
                if (english == std::string("ok"))
                {
                    break;
                }
                std::cout << "Enter chinese # ";
                getline(std::cin, chinese);
                entry += english;
                entry += ": ";
                entry += chinese;
                fprintf(fp, "%s", "\n");
                fprintf(fp, "%s", entry.c_str());
            }
            fclose(fp);
        }
        else
        {
            std::cerr << "Usage: " << argv[0] << " local-port " << "i" << std::endl;
            exit(0);
        }
    }

    uint16_t port = std::stoi(argv[1]);
    // std::string ss = "8888";
    // uint16_t port = std::stoi(ss);
    EnableScreen();
    inetAddr localaddr("0.0.0.0", port);

    // 只处理新链接的到来的接口
    Listener listener(port);

    IOService parse;
    // ###################################

    // std::unique_ptr<TCPSocket> usvr = std::make_unique<TCPSocket>( );
    // ####################################

    // 只处理普通套接字的接口
    HandleConnection handlemet(std::bind(&IOService::IOexecute, &parse, std::placeholders::_1));

    // 下面是 Reactor 做事件派发的
    std::unique_ptr<Reactor> R = std::make_unique<Reactor>();

    // 下面两句话都只是把bind后的 产生的可调用对象传给反应堆的成员
    // 但是这两句话中的可调用对象没有进行实例化
    R->set_OnConnect(std::bind(&Listener::accepter, &listener, std::placeholders::_1));
    R->set_OnNormalHandler(
        std::bind(&HandleConnection::HandleRecvr, &handlemet, std::placeholders::_1),
        std::bind(&HandleConnection::HandleSender, &handlemet, std::placeholders::_1),
        std::bind(&HandleConnection::HandleExceptr, &handlemet, std::placeholders::_1));

    // 下面这句话给bind的accepter这个函数传递了实例化后的myconnection* conn对象
    R->AddConnection(listener.listensockfd(), EPOLLIN | EPOLLET, localaddr, ListenConnection);

    R->Dispatch();

    return 0;
}